package com.superms.platform.shiro;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jeesuite.cache.command.RedisObject;
import com.jeesuite.cache.redis.JedisProviderFactory;
import com.jeesuite.common.util.ResourceUtils;

import redis.clients.util.SafeEncoder;

public class RedisSessionDAO extends AbstractSessionDAO {

	private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class);
	
	private static final int SESSION_EXPIRE_SECONDS = ResourceUtils.getInt("auth.session.expire.seconds", 7200);

	private String keyPrefix = "shiro_session:";
	
	@Override
	public void update(Session session) throws UnknownSessionException {
		this.saveSession(session);
	}
	
	/**
	 * save session
	 * @param session
	 * @throws UnknownSessionException
	 */
	private void saveSession(Session session) throws UnknownSessionException{
		if(session == null || session.getId() == null){
			logger.error("session or session id is null");
			return;
		}
		new RedisObject(keyPrefix + session.getId()).set(session, SESSION_EXPIRE_SECONDS);
	}

	@Override
	public void delete(Session session) {
		if(session == null || session.getId() == null){
			logger.error("session or session id is null");
			return;
		}
		new RedisObject(keyPrefix + session.getId()).remove();

	}

	@Override
	public Collection<Session> getActiveSessions() {
		Set<Session> sessions = new HashSet<Session>();
		
		try {
			Set<byte[]> keys = JedisProviderFactory.getMultiKeyBinaryCommands(null).keys(SafeEncoder.encode(keyPrefix +"*"));
			if(keys != null && keys.size()>0){
				for(byte[] key:keys){
					Session session = new RedisObject(SafeEncoder.encode(key)).get();
					sessions.add(session);
				}
			}
			
		} finally {
			JedisProviderFactory.getJedisProvider(null).release();
		}
		return sessions;
	}

	@Override
	protected Serializable doCreate(Session session) {
		Serializable sessionId = this.generateSessionId(session);  
        this.assignSessionId(session, sessionId);
        this.saveSession(session);
		return sessionId;
	}

	@Override
	protected Session doReadSession(Serializable sessionId) {
		if(sessionId == null){
			logger.error("session id is null");
			return null;
		}
		Session session = new RedisObject(keyPrefix + sessionId).get();
		return session;
	}
}

